package com.mbds.activities;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender.SendIntentException;
import android.content.SharedPreferences;
import android.location.Location;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.widget.Toast;

import com.example.sismapp.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterManager;
import com.google.maps.android.clustering.view.DefaultClusterRenderer;
import com.google.maps.android.ui.IconGenerator;
import com.mbds.P2Pnetwork.NetworkP2P;
import com.mbds.P2Pnetwork.Server;
import com.mbds.accelerometer.SensorDataManager;
import com.mbds.map.NetWork;
import com.mbds.map.Person;

public class MapActivity extends Abs_Activity implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,LocationListener  {
	private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
	
	private static final int MILLISECONDS_PER_SECOND = 1000;
	private static final int SECOND_PER_MINUTE = 60;
	private static final int UPDATE_INTERVAL_IN_MINUTE = 5;
	private static final int UPDATE_LOCATION_INTERVAL = UPDATE_INTERVAL_IN_MINUTE 
			* SECOND_PER_MINUTE  * MILLISECONDS_PER_SECOND;
	
	private GoogleMap map;
	private ClusterManager<Person> clusterManager;
	
	private static LocationClient locationClient;
	private LocationRequest locationRequest;
	
	private SharedPreferences sharedPref ;
	
	private NetWork netWork;
	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_map);
//		SensorDataManager.init(getApplicationContext());
		
		map = ((SupportMapFragment) getSupportFragmentManager()
				.findFragmentById(R.id.map)).getMap();
		
		sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
		NetWork.init();
		netWork = NetWork.getInstance();
		locationClient = new LocationClient(this, this, this);
		connectGooglePlayService();
		
		NetworkP2P.init((WifiManager) getSystemService(Context.WIFI_SERVICE), getApplicationContext());
		
		//Check if the preference Location is active
		if(sharedPref.getBoolean(MainActivity.getLOCATION_KEY(), true)) {
			locationClient.connect();
		}
		
		locationRequest = LocationRequest.create();
		locationRequest.setInterval(UPDATE_LOCATION_INTERVAL);
		
		LocalBroadcastManager.getInstance(this).registerReceiver(new NetWorkBroadcastReceiver(), new IntentFilter(Server.BROACAST_RECEIVE_ACTION));
			
		initIconCluster();

	}
	
	@Override
	protected void onResume() {
		super.onResume();			
		setUpIconCluster();
	}
	
	
		
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(requestCode==CONNECTION_FAILURE_RESOLUTION_REQUEST &&
				resultCode == Activity.RESULT_OK) {
			connectGooglePlayService();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.map, menu);
		return true;
	}
	
	private void initIconCluster() {
		clusterManager = new ClusterManager<Person>(this, map);
		clusterManager
				.setRenderer(new PersonRenderer(IconGenerator.STYLE_GREEN));
		map.setOnCameraChangeListener(clusterManager);
	}

	private void setUpIconCluster() {
		netWork.maj();
				
		//If the location is disabled, we don't have the location of the user
		if(locationClient.isConnected()) {
			String login = sharedPref.getString(MainActivity.getLOGIN_KEY_STRING(), "");
			//Center the camera on the position of the user
			map.moveCamera(CameraUpdateFactory.newLatLngZoom(netWork.getPerson(login).getPosition(), 10));
			netWork.resetTTL(login);
			
			
		}
				
		clusterManager.clearItems();
		for (Person p : netWork.getPersons()) {
			clusterManager.addItem(p);
		}
		clusterManager.cluster();
	}

	private void connectGooglePlayService() {
		int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		
		if(ConnectionResult.SUCCESS != resultCode) {
			GooglePlayServicesUtil.getErrorDialog(resultCode, this, 
					CONNECTION_FAILURE_RESOLUTION_REQUEST).show();
			
		}
		
	}
	
	@Override
	public void onConnectionFailed(ConnectionResult connectionResult) {
		if(connectionResult.hasResolution()) {
			try {
				connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
			} catch(SendIntentException e) {}
		} else {
			GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), this,
					CONNECTION_FAILURE_RESOLUTION_REQUEST);
		}
		
	}

	@Override
	public void onConnected(Bundle arg0) {
		locationClient.requestLocationUpdates(locationRequest, this);
		updateLocationUser(locationClient.getLastLocation());
	}

	@Override
	public void onDisconnected() {
		locationClient.removeLocationUpdates(this);
	}
	
	public static void connectLocationClient() {
		if(locationClient != null) {
			locationClient.connect();
		}
	}
	
	public static void disconnectLocationClient() {
		if(locationClient != null) {
			locationClient.disconnect();
		}
	}
	
	/**
	 * Personalize the items on the map
	 *
	 */
	private class PersonRenderer extends DefaultClusterRenderer<Person> {
		private final IconGenerator iconGenerator;

		public PersonRenderer(int style) {
			super(getApplicationContext(), map, clusterManager);
			iconGenerator = new IconGenerator(getApplicationContext());
			iconGenerator.setStyle(style);
		}

		@Override
		protected void onBeforeClusterItemRendered(Person person,
				MarkerOptions markerOptions) {
			markerOptions.icon(BitmapDescriptorFactory.fromBitmap(iconGenerator
					.makeIcon(person.getPseudo())));
		}

		@Override
		protected boolean shouldRenderAsCluster(Cluster<Person> cluster) {
			return cluster.getSize() > 1;
		}
	}

	@Override
	public void onLocationChanged(Location newLocation) {
		updateLocationUser(newLocation);
	}
	
	private void updateLocationUser(Location newLocation) {
		String login = sharedPref.getString(MainActivity.getLOGIN_KEY_STRING(), "");
		netWork.addPerson(login, newLocation.getLatitude(), newLocation.getLongitude());
//		netWork.addPerson("person2", newLocation.getLatitude()-0.0201, newLocation.getLongitude());
//		netWork.addPerson("person3", newLocation.getLatitude()-0.0201 , newLocation.getLongitude());
		setUpIconCluster();
	}
	
	 private class NetWorkBroadcastReceiver extends BroadcastReceiver {
			@Override
			public void onReceive(Context context, Intent intent) {
				Toast.makeText(getApplicationContext(), intent.getStringExtra(Server.STATUS), Toast.LENGTH_LONG).show();
				
			}
	    }
	 
	 private class InfoConnectionUpdateReceiver extends BroadcastReceiver {
		 @Override
		 public void onReceive(Context arg0, Intent arg1) {
			 WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
			 boolean isConnected = ((NetworkInfo) arg1.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO)).isConnected();
			 int ip =	wifiManager.getConnectionInfo().getIpAddress();

			 if(ip != 0 && isConnected) {
				 String ipString = String.format(
						 "%d.%d.%d.%d",
						 (ip & 0xff),
						 (ip >> 8 & 0xff),
						 (ip >> 16 & 0xff),
						 (ip >> 24 & 0xff));

				 Toast.makeText(getApplicationContext(),"connected", Toast.LENGTH_LONG).show();
			 }
		 }
	 }
}
